﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using System.IO;
using System.Xml;
using System.Collections;


namespace Zxb.DayWork.Core
{
    public class ReflectionAssistant
    {

        public static void ReflectFromConfigFile()
        {
            PrepareAssembly();

            ParseConfigAndRun();
        }

        public static void PrepareAssembly()
        {
            string path = string.Concat(AppDomain.CurrentDomain.BaseDirectory, "dll");
            string[] fileEntries = Directory.GetFiles(path);
            foreach (string fileentry in fileEntries)
            {
                Assembly asm = CacheAssistant.GetData(fileentry) as Assembly;
                if (asm == null)
                {
#if DEBUG
                    asm = Assembly.LoadFile(fileentry);
#else
                    byte[] buf = System.IO.File.ReadAllBytes(fileentry);
                    asm = Assembly.Load(buf);
#endif
                    FileDependency fileDep = new FileDependency(fileentry);
                    CacheAssistant.Add(fileentry, asm, fileDep);
                }
            }
        }

        public static void ParseConfigAndRun()
        {
            XmlDocument xmldoc = new XmlDocument();
            string path = string.Concat(AppDomain.CurrentDomain.BaseDirectory, "DayWorkClass.config");
            xmldoc.Load(path);

            XmlNodeList list = xmldoc.SelectNodes("configuration/components/component");
            foreach (XmlNode node in list)
            {
                string typeinfo = node.Attributes["type"].Value;
                Type t = FindType(typeinfo);

                ArrayList types = new ArrayList();
                ArrayList plist = new ArrayList();
                XmlNodeList paramList = node.SelectNodes("param");
                foreach (XmlNode pnode in paramList)
                {
                    string ptype = pnode.Attributes["type"].Value;
                    string pvalue = pnode.Attributes["value"].Value;

                    Type pt = FindType(ptype);
                    object p = GetParam(pt, pvalue);
                    types.Add(pt);
                    plist.Add(p);
                }
                //空数组 对应 无参数构造函数
                ConstructIRun(t, types.ToArray().Cast<Type>().ToArray(), plist.ToArray());
            }
        }

        public static void ConstructIRun(Type t, Type[] ptypes, object[] objs)
        {
            try
            {
                ConstructorInfo ci = t.GetConstructor(ptypes);
                object o = ci.Invoke(objs);
                Logger.InfoLog.Info(string.Concat(t.FullName, "执行开始"));
                ((IRun)o).Run();
                Logger.InfoLog.Info(string.Concat(t.FullName, "执行结束"));
            }
            catch(Exception ex)
            {
                Logger.InfoLog.Error(string.Format("Type:{0},异常:{1}", t.FullName, ex.Message));
            }
        }

        public static Type FindType(string ptype)
        {
            Type tt = null;
            tt = Type.GetType(ptype);
            if (tt != null)
            {
                return tt;
            }
            foreach (object o in CacheAssistant.Values)
            {
                Assembly asm = o as Assembly;
                tt = asm.GetType(ptype, false, true);
                if (tt != null)
                {
                    break;
                }
            }
            return tt;
        }

        public static object GetParam(Type t, string value)
        {
            object result = null;
            if (t.IsEnum)
            {
                result = Enum.Parse(t, value);
                return result;
            }
            result = Convert.ChangeType(value, t);
            return result;
        }
    }
}
